﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Linq.Expressions;
using System.Reflection;

namespace Milo.Framework
{
    public class ActionMethodInfo
    {
        private LambdaExpression action;
        private bool done = false;
        public bool IsIdMethod;
        public object Id;
        public string ControllerName;
        public Type ControllerType;
        public string ActionName;
        public IDictionary<string, object> Parameters;

        public ActionMethodInfo(LambdaExpression action)
        {
            this.action = action;

			Ensure();
        }

        public void Ensure()
        {
            if (done)
                return;

            MethodCallExpression methodExpression = (MethodCallExpression)action.Body;
            ActionName = methodExpression.Method.Name;
            ControllerType = methodExpression.Object.Type;
            ControllerName = ControllerType.Name.Replace("Controller", string.Empty);

            IsIdMethod = methodExpression.Method.GetParameters().Where(p => p.Name.Equals("ID", StringComparison.CurrentCultureIgnoreCase)).SingleOrDefault() != null;

            Parameters = new Dictionary<string, object>();

            if (IsIdMethod)
            {
                Id = Expression.Lambda(methodExpression.Arguments[0]).Compile().DynamicInvoke();
                Parameters.Add("id", Id);
            }
            else
            {
                ParameterInfo[] pis = methodExpression.Method.GetParameters();

                int c = pis.Length;

                for (int i = 0; i < c; i++)
                {
                    object var = Expression.Lambda(methodExpression.Arguments[i]).Compile().DynamicInvoke();

                    Parameters.Add(pis[i].Name, var);
                }
            }

            foreach (object ma in methodExpression.Method.GetCustomAttributes(false))
                if (ma is System.Web.Mvc.ActionNameAttribute)
                    ActionName = ((System.Web.Mvc.ActionNameAttribute)ma).Name;

            done = true;
        }
    }
}
